home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / dev / lang / Python16.lha / Python-1.6 / Lib / Python1.6 / distutils / unixccompiler.py < prev    next >
Encoding:
Python Source  |  2000-08-04  |  12.6 KB  |  344 lines

  1. """distutils.unixccompiler
  2.  
  3. Contains the UnixCCompiler class, a subclass of CCompiler that handles
  4. the "typical" Unix-style command-line C compiler:
  5.   * macros defined with -Dname[=value]
  6.   * macros undefined with -Uname
  7.   * include search directories specified with -Idir
  8.   * libraries specified with -lllib
  9.   * library search directories specified with -Ldir
  10.   * compile handled by 'cc' (or similar) executable with -c option:
  11.     compiles .c to .o
  12.   * link static library handled by 'ar' command (possibly with 'ranlib')
  13.   * link shared library handled by 'cc -shared'
  14. """
  15.  
  16. # created 1999/07/05, Greg Ward
  17.  
  18. __revision__ = "$Id: unixccompiler.py,v 1.30 2000/08/04 01:28:39 gward Exp $"
  19.  
  20. import string, re, os
  21. from types import *
  22. from copy import copy
  23. from distutils.dep_util import newer
  24. from distutils.ccompiler import \
  25.      CCompiler, gen_preprocess_options, gen_lib_options
  26. from distutils.errors import \
  27.      DistutilsExecError, CompileError, LibError, LinkError
  28.  
  29. # XXX Things not currently handled:
  30. #   * optimization/debug/warning flags; we just use whatever's in Python's
  31. #     Makefile and live with it.  Is this adequate?  If not, we might
  32. #     have to have a bunch of subclasses GNUCCompiler, SGICCompiler,
  33. #     SunCCompiler, and I suspect down that road lies madness.
  34. #   * even if we don't know a warning flag from an optimization flag,
  35. #     we need some way for outsiders to feed preprocessor/compiler/linker
  36. #     flags in to us -- eg. a sysadmin might want to mandate certain flags
  37. #     via a site config file, or a user might want to set something for
  38. #     compiling this module distribution only via the setup.py command
  39. #     line, whatever.  As long as these options come from something on the
  40. #     current system, they can be as system-dependent as they like, and we
  41. #     should just happily stuff them into the preprocessor/compiler/linker
  42. #     options and carry on.
  43.  
  44.  
  45. class UnixCCompiler (CCompiler):
  46.  
  47.     compiler_type = 'unix'
  48.  
  49.     # These are used by CCompiler in two places: the constructor sets
  50.     # instance attributes 'preprocessor', 'compiler', etc. from them, and
  51.     # 'set_executable()' allows any of these to be set.  The defaults here
  52.     # are pretty generic; they will probably have to be set by an outsider
  53.     # (eg. using information discovered by the sysconfig about building
  54.     # Python extensions).
  55.     executables = {'preprocessor' : None,
  56.                    'compiler'     : ["cc"],
  57.                    'compiler_so'  : ["cc"],
  58.                    'linker_so'    : ["cc", "-shared"],
  59.                    'linker_exe'   : ["cc"],
  60.                    'archiver'     : ["ar", "-cr"],
  61.                    'ranlib'       : None,
  62.                   }
  63.  
  64.     # Needed for the filename generation methods provided by the base
  65.     # class, CCompiler.  NB. whoever instantiates/uses a particular
  66.     # UnixCCompiler instance should set 'shared_lib_ext' -- we set a
  67.     # reasonable common default here, but it's not necessarily used on all
  68.     # Unices!
  69.  
  70.     src_extensions = [".c",".C",".cc",".cxx",".cpp"]
  71.     obj_extension = ".o"
  72.     static_lib_extension = ".a"
  73.     shared_lib_extension = ".so"
  74.     static_lib_format = shared_lib_format = "lib%s%s"
  75.  
  76.  
  77.  
  78.     def __init__ (self,
  79.                   verbose=0,
  80.                   dry_run=0,
  81.                   force=0):
  82.         CCompiler.__init__ (self, verbose, dry_run, force)
  83.  
  84.  
  85.     def preprocess (self,
  86.                     source,
  87.                     output_file=None,
  88.                     macros=None,
  89.                     include_dirs=None,
  90.                     extra_preargs=None,
  91.                     extra_postargs=None):
  92.  
  93.         (_, macros, include_dirs) = \
  94.             self._fix_compile_args (None, macros, include_dirs)
  95.         pp_opts = gen_preprocess_options (macros, include_dirs)
  96.         pp_args = self.preprocessor + pp_opts
  97.         if output_file:
  98.             pp_args.extend(['-o', output_file])
  99.         if extra_preargs:
  100.             pp_args[:0] = extra_preargs
  101.         if extra_postargs:
  102.             extra_postargs.extend(extra_postargs)
  103.  
  104.         # We need to preprocess: either we're being forced to, or the
  105.         # source file is newer than the target (or the target doesn't
  106.         # exist).
  107.         if self.force or (output_file and newer(source, output_file)):
  108.             if output_file:
  109.                 self.mkpath(os.path.dirname(output_file))
  110.             try:
  111.                 self.spawn (pp_args)
  112.             except DistutilsExecError, msg:
  113.                 raise CompileError, msg
  114.  
  115.  
  116.     def compile (self,
  117.                  sources,
  118.                  output_dir=None,
  119.                  macros=None,
  120.                  include_dirs=None,
  121.                  debug=0,
  122.                  extra_preargs=None,
  123.                  extra_postargs=None):
  124.  
  125.         (output_dir, macros, include_dirs) = \
  126.             self._fix_compile_args (output_dir, macros, include_dirs)
  127.         (objects, skip_sources) = self._prep_compile (sources, output_dir)
  128.  
  129.         # Figure out the options for the compiler command line.
  130.         pp_opts = gen_preprocess_options (macros, include_dirs)
  131.         cc_args = pp_opts + ['-c']
  132.         if debug:
  133.             cc_args[:0] = ['-g']
  134.         if extra_preargs:
  135.             cc_args[:0] = extra_preargs
  136.         if extra_postargs is None:
  137.             extra_postargs = []
  138.  
  139.         # Compile all source files that weren't eliminated by
  140.         # '_prep_compile()'.        
  141.         for i in range (len (sources)):
  142.             src = sources[i] ; obj = objects[i]
  143.             if skip_sources[src]:
  144.                 self.announce ("skipping %s (%s up-to-date)" % (src, obj))
  145.             else:
  146.                 self.mkpath (os.path.dirname (obj))
  147.                 try:
  148.                     self.spawn (self.compiler_so + cc_args +
  149.                                 [src, '-o', obj] +
  150.                                 extra_postargs)
  151.                 except DistutilsExecError, msg:
  152.                     raise CompileError, msg
  153.  
  154.         # Return *all* object filenames, not just the ones we just built.
  155.         return objects
  156.  
  157.     # compile ()
  158.     
  159.  
  160.     def create_static_lib (self,
  161.                            objects,
  162.                            output_libname,
  163.                            output_dir=None,
  164.                            debug=0):
  165.  
  166.         (objects, output_dir) = self._fix_object_args (objects, output_dir)
  167.  
  168.         output_filename = \
  169.             self.library_filename (output_libname, output_dir=output_dir)
  170.  
  171.         if self._need_link (objects, output_filename):
  172.             self.mkpath (os.path.dirname (output_filename))
  173.             self.spawn (self.archiver +
  174.                         [output_filename] +
  175.                         objects + self.objects)
  176.  
  177.             # Not many Unices required ranlib anymore -- SunOS 4.x is, I
  178.             # think the only major Unix that does.  Maybe we need some
  179.             # platform intelligence here to skip ranlib if it's not
  180.             # needed -- or maybe Python's configure script took care of
  181.             # it for us, hence the check for leading colon.
  182.             if self.ranlib:
  183.                 try:
  184.                     self.spawn (self.ranlib + [output_filename])
  185.                 except DistutilsExecError, msg:
  186.                     raise LibError, msg
  187.         else:
  188.             self.announce ("skipping %s (up-to-date)" % output_filename)
  189.  
  190.     # create_static_lib ()
  191.  
  192.  
  193.     def link_shared_lib (self,
  194.                          objects,
  195.                          output_libname,
  196.                          output_dir=None,
  197.                          libraries=None,
  198.                          library_dirs=None,
  199.                          runtime_library_dirs=None,
  200.                          export_symbols=None,
  201.                          debug=0,
  202.                          extra_preargs=None,
  203.                          extra_postargs=None,
  204.                          build_temp=None):
  205.  
  206.         self.link_shared_object (
  207.             objects,
  208.             self.library_filename (output_libname, lib_type='shared'),
  209.             output_dir,
  210.             libraries,
  211.             library_dirs,
  212.             runtime_library_dirs,
  213.             export_symbols,
  214.             debug,
  215.             extra_preargs,
  216.             extra_postargs,
  217.             build_temp)
  218.         
  219.  
  220.     def link_shared_object (self,
  221.                             objects,
  222.                             output_filename,
  223.                             output_dir=None,
  224.                             libraries=None,
  225.                             library_dirs=None,
  226.                             runtime_library_dirs=None,
  227.                             export_symbols=None,
  228.                             debug=0,
  229.                             extra_preargs=None,
  230.                             extra_postargs=None,
  231.                             build_temp=None):
  232.  
  233.         (objects, output_dir) = self._fix_object_args (objects, output_dir)
  234.         (libraries, library_dirs, runtime_library_dirs) = \
  235.             self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
  236.  
  237.         lib_opts = gen_lib_options (self,
  238.                                     library_dirs, runtime_library_dirs,
  239.                                     libraries)
  240.         if type (output_dir) not in (StringType, NoneType):
  241.             raise TypeError, "'output_dir' must be a string or None"
  242.         if output_dir is not None:
  243.             output_filename = os.path.join (output_dir, output_filename)
  244.  
  245.         if self._need_link (objects, output_filename):
  246.             ld_args = (objects + self.objects + 
  247.                        lib_opts + ['-o', output_filename])
  248.             if debug:
  249.                 ld_args[:0] = ['-g']
  250.             if extra_preargs:
  251.                 ld_args[:0] = extra_preargs
  252.             if extra_postargs:
  253.                 ld_args.extend (extra_postargs)
  254.             self.mkpath (os.path.dirname (output_filename))
  255.             try:
  256.                 self.spawn (self.linker_so + ld_args)
  257.             except DistutilsExecError, msg:
  258.                 raise LinkError, msg
  259.         else:
  260.             self.announce ("skipping %s (up-to-date)" % output_filename)
  261.  
  262.     # link_shared_object ()
  263.  
  264.  
  265.     def link_executable (self,
  266.                          objects,
  267.                          output_progname,
  268.                          output_dir=None,
  269.                          libraries=None,
  270.                          library_dirs=None,
  271.                          runtime_library_dirs=None,
  272.                          debug=0,
  273.                          extra_preargs=None,
  274.                          extra_postargs=None):
  275.     
  276.         (objects, output_dir) = self._fix_object_args (objects, output_dir)
  277.         (libraries, library_dirs, runtime_library_dirs) = \
  278.             self._fix_lib_args (libraries, library_dirs, runtime_library_dirs)
  279.  
  280.         lib_opts = gen_lib_options (self,
  281.                                     library_dirs, runtime_library_dirs,
  282.                                     libraries)
  283.         output_filename = output_progname # Unix-ism!
  284.         if output_dir is not None:
  285.             output_filename = os.path.join (output_dir, output_filename)
  286.  
  287.         if self._need_link (objects, output_filename):
  288.             ld_args = objects + self.objects + lib_opts + ['-o', output_filename]
  289.             if debug:
  290.                 ld_args[:0] = ['-g']
  291.             if extra_preargs:
  292.                 ld_args[:0] = extra_preargs
  293.             if extra_postargs:
  294.                 ld_args.extend (extra_postargs)
  295.             self.mkpath (os.path.dirname (output_filename))
  296.             try:
  297.                 self.spawn (self.linker_exe + ld_args)
  298.             except DistutilsExecError, msg:
  299.                 raise LinkError, msg
  300.         else:
  301.             self.announce ("skipping %s (up-to-date)" % output_filename)
  302.  
  303.     # link_executable ()
  304.  
  305.  
  306.     # -- Miscellaneous methods -----------------------------------------
  307.     # These are all used by the 'gen_lib_options() function, in
  308.     # ccompiler.py.
  309.     
  310.     def library_dir_option (self, dir):
  311.         return "-L" + dir
  312.  
  313.     def runtime_library_dir_option (self, dir):
  314.         return "-R" + dir
  315.  
  316.     def library_option (self, lib):
  317.         return "-l" + lib
  318.  
  319.  
  320.     def find_library_file (self, dirs, lib, debug=0):
  321.  
  322.         for dir in dirs:
  323.             shared = os.path.join (
  324.                 dir, self.library_filename (lib, lib_type='shared'))
  325.             static = os.path.join (
  326.                 dir, self.library_filename (lib, lib_type='static'))
  327.  
  328.             # We're second-guessing the linker here, with not much hard
  329.             # data to go on: GCC seems to prefer the shared library, so I'm
  330.             # assuming that *all* Unix C compilers do.  And of course I'm
  331.             # ignoring even GCC's "-static" option.  So sue me.
  332.             if os.path.exists (shared):
  333.                 return shared
  334.             elif os.path.exists (static):
  335.                 return static
  336.  
  337.         else:
  338.             # Oops, didn't find it in *any* of 'dirs'
  339.             return None
  340.  
  341.     # find_library_file ()
  342.  
  343. # class UnixCCompiler
  344.